<template>
  <g>
    <circle :r="5" :cx="x" :cy="y" fill="#999" :stroke="color" stroke-width="2"/>
    <circle :r="5" :cx="x" :cy="y" fill="rgba(0, 0, 0, 0)" stroke="rgba(0, 0, 0, 0)" stroke-width="2" ref="node" @mouseover="mouseover" @mouseout="mouseout"/>
  </g>
</template>

<script>
import { TweenMax } from 'gsap'
import Draggable from 'gsap/Draggable'
// import { createLine } from '@/js/nodehelper'

export default {
  props: {
    borderColor: {
      default: '#666'
    },
    cursor: {
      default: 'default'
    },
    bounds: {
      default: '.container'
    },
    category: { // 1头结点2尾结点
      default: 1
    }
  },
  data () {
    return {
      isMouseOver: false, // 是否鼠标移入
      point: { x: 0, y: 0 }, // 中心点
      tempPoint: { x: 0, y: 0 }, // 鼠标移动点
      tempX: 0,
      tempY: 0
    }
  },
  methods: {
    mouseover () {
      this.isMouseOver = true
    },
    mouseout () {
      this.isMouseOver = false
    },
    /**
     * 更新节点的中心位置，并触发update事件
     * @Author   Jiangzhiwei
     * @datetime 2021-10-21T10:11:12+0800
     */
    refreshPoint () {
      const box = this.container.$el
      const containerRect = box.getBoundingClientRect()
      const nodeRect = this.$refs.node.getBoundingClientRect()
      const x = (nodeRect.left + nodeRect.right) / 2 - containerRect.left
      const y = (nodeRect.top + nodeRect.bottom) / 2 - containerRect.top
      this.point.x = x
      this.point.y = y
      this.$emit('update', this.point)
      // console.log(this.point.x, ',', this.point.y)
    },
    /**
     * 更新连接节点时的线的终点
     * @param    {Object} event 事件
     * @Author   Jiangzhiwei
     * @datetime 2021-10-21T10:12:37+0800
     */
    refreshTempPoint (event) {
      const box = this.container.$el
      const containerRect = box.getBoundingClientRect()
      this.tempPoint.x = event.clientX - containerRect.left
      this.tempPoint.y = event.clientY - containerRect.top
      // console.log(this.tempPoint.x, ',', this.tempPoint.y)
    },
    /**
     * 获取拖动时移入的节点
     * @return   {Object} 移入的节点组件
     * @Author   Jiangzhiwei
     * @datetime 2021-10-21T10:13:37+0800
     */
    getNode () {
      let node = null
      this.container.getNodeComps().some(item => {
        // 不是父级节点 且 与另一节点重合
        if (item.id !== this.$parent.id && this.node.hitTest(item.$el)) {
          // 再判断两节点是否已经连接过
          let nodeIds
          if (this.category === 1) { // 如果是头节点，则在后面
            nodeIds = ',' + item.id + ',' + this.$parent.id + ','
          } else { // 反之，则在前面
            nodeIds = ',' + this.$parent.id + ',' + item.id + ','
          }
          const lines = this.container.getLines()
          if (lines.some(line => line.nodeIds === nodeIds)) { // 已连接
            return false
          } else { // 未连接
            node = item
            return true
          }
        }
        return false
      })
      return node
    },
    /**
     * 新增连线 虚线
     * @Author   Jiangzhiwei
     * @datetime 2021-10-21T15:26:47+0800
     */
    addLine () {
      if (this.category === 1) { // 头节点
        this.lineData = { head: this.tempPoint, tail: this.point, nodeIds: `${this.$parent.id}` }
      } else { // 尾结点
        this.lineData = { head: this.point, tail: this.tempPoint, nodeIds: `${this.$parent.id}` }
      }
      this.id = this.container.addLine(this.lineData)
    },
    /**
     * 更新连线 虚线
     * @Author   Jiangzhiwei
     * @datetime 2021-10-21T15:27:03+0800
     */
    updateLine () {
      if (this.category === 1) {
        this.lineData.head = this.tempPoint
      } else {
        this.lineData.tail = this.tempPoint
      }
    },
    /**
     * 连接节点
     * @param    {Object} node node组件
     * @param    {Boolean} isOver 是否创建完成
     * @Author   Jiangzhiwei
     * @datetime 2021-10-21T10:14:18+0800
     */
    link (node, isOver) {
      if (this.category === 1) { // 头节点
        this.lineData.head = node.tail
      } else { // 尾节点
        this.lineData.tail = node.head
      }
      if (isOver) {
        if (this.category === 1) { // 头节点
          this.lineData.nodeIds = ',' + node.id + ',' + this.lineData.nodeIds + ','
        } else { // 尾节点
          this.lineData.nodeIds = ',' + this.lineData.nodeIds + ',' + node.id + ','
        }
        // 根据id查找对应的线组件
        const line = this.container.getLineComps().find(item => item.id === this.lineData.id)
        line.setOver()
        // 记录历史
        this.container.addHistory({
          type: 'addLine',
          data: this.lineData
        })
      }
    },
    init () {
      this.node = Draggable.create(this.$refs.node, {
        cursor: this.cursor,
        activeCursor: this.cursor,
        onPress: event => {
          event.stopPropagation()
          this.$parent.disableDrag() // 禁止父节点拖动
          this.tempX = event.clientX
          this.tempY = event.clientY
          this.refreshPoint()
          this.refreshTempPoint(event)
          this.addLine()
          // this.line = createLine(this.bounds, { head: this.point, tail: this.tempPoint })
        },
        onDrag: event => {
          // console.log('onDrag')
          const node = this.getNode()
          if (node) { // 重合
            this.link(node)
          } else { // 没有重合
            this.refreshTempPoint(event)
            this.updateLine()
          }
        },
        onMove: event => {
          // console.log('onMove')
        },
        onRelease: event => {
          // console.log('onRelease')
          this.$parent.enableDrag() // 允许父节点拖动
          const node = this.getNode()
          if (node) { // 重合
            this.link(node, true)
          } else { // 没有重合
            this.container.removeLine(this.id)
          }
          TweenMax.to(this.$refs.node, 0, { x: 0, y: 0 })
        }
      })[0]
      this.refreshPoint()
      // this.$refs.node.addEventListener('mouseover', this.mouseOver)
      // this.$refs.node.addEventListener('mouseout', this.mouseOut)
    }
  },
  computed: {
    x () {
      if (this.category === 1) {
        return 0
      } else {
        return 120
      }
    },
    y () {
      return 15
    },
    color () {
      return this.isMouseOver ? '#eee' : this.borderColor
    },
    container () {
      return this.$parent.$parent
    }
  },
  mounted () {
    this.init()
  }
}
</script>
